﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using WebNext.Domain.Interfaces;
using WebNext.Domain.Entities;
using WebNext.UI.Utils;
using WebNext.UI.Models.Comments;
using WebNext.UI.Properties;
using WebNext.Domain;
using WebNext.UI.Models;

namespace WebNext.UI.Controllers
{
	public class CommentsController : BaseController
	{
		protected IEntriesRepository entriesRepository;
		protected IDatabaseContext dataBaseContext;

		public CommentsController(IEntriesRepository entriesRepository, IDatabaseContext dataBaseContext)
		{
			this.entriesRepository = entriesRepository;
			this.entriesRepository.CultureId = this.CultureId;
			this.dataBaseContext = dataBaseContext;
		}

		[HttpPost]
		[ValidateInput(false)]
		public virtual ActionResult SaveComment(CommentViewModel commentModel)
		{
			Entry entry = this.entriesRepository.GetById(commentModel.EntryId);
			if (entry != null)
			{
				ValidationResult validationResult = commentModel.Validate();
				if (!validationResult.IsValid)
				{
					this.TempData[Constants.Message] = validationResult.GetErrorsMessage();
					this.TempData[Constants.Temp] = commentModel;
				}
				else
				{
					this.EditComment(commentModel, entry);
					this.Session[Constants.EditedCommentId] = null;
				}
				MainViewType viewType = ViewTypeConverter.GetViewTypeByEntryType(entry.Type);
				return this.RedirectToAction("View", "Entries", new { viewType = viewType, entryId = entry.Id });
			}
			else
			{
				this.TempData[Constants.Message] = string.Format(Resources.EntryOfIdNotFound, commentModel.EntryId);
				return this.RedirectToAction("List", "Entries", new { viewType = MainViewType.Blog, pageNumber = 1 });
			}
		}

		[HttpPost]
		[ValidateInput(false)]
		public ActionResult SaveCommentAjax(CommentViewModel commentModel)
		{
			CommentAjaxViewModel viewModel = new CommentAjaxViewModel();
			viewModel.CommentModel = commentModel;
					   
			Entry entry = this.entriesRepository.GetById(commentModel.EntryId);
		   if (entry != null)
		   {
				ValidationResult validationResult = commentModel.Validate();
				if (!validationResult.IsValid)
				{
					viewModel.Result = false;
					viewModel.Message = validationResult.GetErrorsMessage();
				}
				else
				{
					viewModel.Result = true;
					viewModel.CommentsCount = entry.Comments.Count + 1;
					
					commentModel.Id = this.EditComment(commentModel, entry);
					commentModel.Created = DateTime.Now;
					commentModel.IsLogged = this.IsLogged;
					viewModel.Message = this.TempData[Constants.Message] as string;
				}

				CaptchaConfiguration captchConfig = CaptchaHelper.CreateCaptcha(this.HttpContext);
				viewModel.CaptchaValueA = captchConfig.A;
				viewModel.CaptchaValueB = captchConfig.B;
				viewModel.CaptchaKey = captchConfig.CaptchaKey;
			}
			else
			{
				viewModel.Result = false;
				viewModel.Message = string.Format(Resources.EntryOfIdNotFound, commentModel.EntryId);
			}
			this.TempData[Constants.Message] = viewModel.Message;
			return this.View("../Entries/CommentAjaxView", viewModel);
		}

		[HttpPost]
		[Authorize]
		public virtual ActionResult CancelEditComment(int entryId)
		{
			Entry entry = this.entriesRepository.GetById(entryId);
			if (entry != null)
			{
				this.Session[Constants.EditedCommentId] = null;
				MainViewType viewType = ViewTypeConverter.GetViewTypeByEntryType(entry.Type);
				return this.RedirectToAction("View", "Entries", new { viewType = viewType, entryId = entry.Id });
			}
			else
			{
				this.TempData[Constants.Message] = string.Format(Resources.EntryOfIdNotFound, entryId);
				return this.RedirectToAction("List", "Entries", new { viewType = MainViewType.Blog, pageNumber = 1 });
			}
		}

		private int EditComment(CommentViewModel commentModel, Entry entry)
		{
			int commentId = 0;
			if (commentModel.Id == 0)
			{
				Comment newComment = new Comment(entry, commentModel.Author, commentModel.Content);
				entry.Comments.Add(newComment);
				this.TempData[Constants.Message] = string.Format(Resources.CommentHasBeenAdded, entry.Title);
				this.dataBaseContext.Dispose();
				commentId = newComment.Id;
			}
			else
			{
				Comment existingComment = entry.Comments.FirstOrDefault(c => c.Id == commentModel.Id);
				if (existingComment != null)
				{
					existingComment.Author = commentModel.Author;
					existingComment.Content = commentModel.Content;
					this.TempData[Constants.Message] = string.Format(Resources.CommentHasBeenUpdated, entry.Title);
					commentId = existingComment.Id;
				}
				else
				{
					this.TempData[Constants.Message] = Resources.EditedCommentNotFound;
				}
			}
			return commentId;
		}

		[HttpPost]
		[Authorize]
		public virtual ActionResult ManageComment(int entryId, int commentId, string action)
		{
			if (action == "delete")
			{
				return this.DeleteComment(entryId, commentId);
			}
			if (action == "edit")
			{
				return this.EditComment(entryId, commentId);
			}
			return this.RedirectToAction("List", "Entries", new { viewType = MainViewType.Blog, pageNumber = 1 });
		}

		private ActionResult DeleteComment(int entryId, int commentId)
		{
			Entry entry = this.entriesRepository.GetById(entryId);
			if (entry != null)
			{
				Comment comment = entry.Comments.FirstOrDefault(c => c.Id == commentId);
				if (comment != null)
				{
					entry.Comments.Remove(comment);
					this.TempData[Constants.Message] = string.Format(Resources.CommentDeleted, entry.Title);
				}
				else
				{
					this.TempData[Constants.Message] = string.Format(Resources.CommentOfIdNotFound, commentId);
				}
				MainViewType viewType = ViewTypeConverter.GetViewTypeByEntryType(entry.Type);
				return this.RedirectToAction("View", "Entries", new { viewType = viewType, entryId = entryId });
			}
			else
			{
				this.TempData[Constants.Message] = string.Format(Resources.EntryOfIdNotFound, entryId);
				return this.RedirectToAction("List", "Entries", new { viewType = MainViewType.Blog, pageNumber = 1 });
			}
		}

		private ActionResult EditComment(int entryId, int commentId)
		{
			Entry entry = this.entriesRepository.GetById(entryId);
			if (entry != null)
			{
				Comment comment = entry.Comments.FirstOrDefault(c => c.Id == commentId);
				if (comment != null)
				{
					this.Session[Constants.EditedCommentId] = commentId;
				}
				else
				{
					this.TempData[Constants.Message] = string.Format(Resources.CommentOfIdNotFound, commentId);
				}
				MainViewType viewType = ViewTypeConverter.GetViewTypeByEntryType(entry.Type);
				return this.RedirectToAction("View", "Entries", new { viewType = viewType, entryId = entryId });
			}
			else
			{
				this.TempData[Constants.Message] = string.Format(Resources.EntryOfIdNotFound, entryId);
				return this.RedirectToAction("List", "Entries", new { viewType = MainViewType.Blog, pageNumber = 1 });
			}
		}

		[HttpPost]
		public virtual ActionResult RankComment(int entryId, int commentId, string action)
		{
			if (action == "+")
			{
				return this.RankComment(entryId, commentId, 1);
			}
			if (action == "-")
			{
				return this.RankComment(entryId, commentId, -1);
			}
			return this.RedirectToAction("List", "Entries", new { viewType = MainViewType.Blog, pageNumber = 1 });
		}

		private ActionResult RankComment(int entryId, int commentId, int value)
		{
			string commentRankKey = string.Format("CommentRank{0}", commentId);
			Entry entry = this.entriesRepository.GetById(entryId);
			if (entry != null)
			{
				Comment comment = entry.Comments.FirstOrDefault(c => c.Id == commentId);
				if (comment == null)
				{
					this.TempData[Constants.Message] = string.Format(Resources.CommentOfIdNotFound, commentId);
				}
				else if (this.Request.Cookies[commentRankKey] != null)
				{
					this.TempData[Constants.Message] = string.Format(Properties.Resources.AlreadyRankedComment, entry.Title);
				}
				else
				{
					comment.Rank += value;
					this.TempData[Constants.Message] = string.Format(Resources.CommentRankSaved, entry.Title);

					HttpCookie cookie = new HttpCookie(commentRankKey, value.ToString());
					cookie.Expires = DateTime.Now.AddYears(5);
					this.HttpContext.Response.Cookies.Set(cookie);
				}
				MainViewType viewType = ViewTypeConverter.GetViewTypeByEntryType(entry.Type);
				return this.RedirectToAction("View", "Entries", new { viewType = viewType, entryId = entryId });
			}
			else
			{
				this.TempData[Constants.Message] = string.Format(Resources.EntryOfIdNotFound, entryId);
				return this.RedirectToAction("List", "Entries", new { viewType = MainViewType.Blog, pageNumber = 1 });
			}
		}

		[HttpPost]
		public JsonResult RankAjax(int entryId, int commentId, int value)
		{
			System.Threading.Thread.Sleep(2000);
			JsonResult result = new JsonResult();

			string commentRankKey = string.Format("CommentRank{0}", commentId);
			Entry entry = this.entriesRepository.GetById(entryId);
			if (entry != null)
			{
				Comment comment = entry.Comments.FirstOrDefault(c => c.Id == commentId);
				if (comment == null)
				{
					result.Data = new { result = false, message = string.Format(Resources.CommentOfIdNotFound, commentId) };
				}
				else if (this.Request.Cookies[commentRankKey] != null)
				{
					result.Data = new { result = false, message = string.Format(Properties.Resources.AlreadyRankedComment, entry.Title) };
				}
				else
				{
					comment.Rank += value;
					result.Data = new { result = true, message = string.Format(Resources.CommentRankSaved, entry.Title), currentRank = comment.Rank };
				}
			}
			else
			{
				result.Data = new { result = false, message = string.Format(Resources.EntryOfIdNotFound, entryId) };
			}
			return result;
		}
	}
}
